package hsp.admin.interceptor;

import hsp.admin.cache.ParamCache;
import hsp.admin.enums.ParamCode;
import hsp.admin.exception.TokenException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Component
public class UserIdInterceptor implements HandlerInterceptor, CommandLineRunner {

    private static final ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    private static final Map<Long, UserIdWrapper> userIdMap = new HashMap<>();

    private long expireTime = 0;

    @Override
    public void run(String... args) {
        expireTime = Long.parseLong(ParamCache.getValueByCode(ParamCode.Expire_Time));

        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleAtFixedRate(() -> userIdMap.forEach((key, value) -> value.setExpire(value.getExpireTime() < System.currentTimeMillis())), 0, expireTime, TimeUnit.SECONDS);
    }

    @Getter
    @Setter
    public static class UserIdWrapper{

        private boolean expire;

        private long expireTime;

    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        long userId = Long.parseLong(request.getHeader("userId"));

        if(userIdMap.get(userId) == null){
            UserIdWrapper wrapper = new UserIdWrapper();
            wrapper.setExpireTime(System.currentTimeMillis() + expireTime * 1000);
            userIdMap.put(userId, wrapper);
        }else {
            userIdMap.get(userId).setExpireTime(System.currentTimeMillis() + expireTime * 1000);
        }
        if(userIdMap.get(userId).isExpire()){
            throw new TokenException("Token过期");
        }
        threadLocal.set(userId);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){
        threadLocal.remove();
    }

    public static long getUserId(){
        return threadLocal.get();
    }

    public static void removeUserId(long id){
        userIdMap.remove(id);
    }

}
